Plasmo を使ってブラウザ拡張機能を作ってみた

Plasmo を使ってブラウザ拡張機能を作ってみた

Clock Icon2024.12.01

こんにちは、森田です。

私は、業務でもプライベートでも Chrome 拡張機能を頻繁に利用しています。

様々な Chrome 拡張が、ストアに公開されていますが、用途によっては公開されている機能に満足できないことが多々ありました。

そのため、学習コストをかけずに Chrome 拡張を作れないかと調査していたところ「Plasmo」と呼ばれるフレームワークを発見しました。

Plasmo とは

Plasmoは、ブラウザ拡張機能用のフレームワークです。

https://www.plasmo.com/

このフレームワークでは、React、Typescriptをサポートしています。

そのため、普段 React を触っている人にとって取り組みやすいものとなっています。

また、Plasmoは、開発サーバーを起動することでライブリローディングしながら開発を行うことができます。

本記事では、 Plasmo を使って Chrome 拡張のチュートリアルを一通りやっていきます。

やってみた

初期セットアップ

npmを使って、初期セットアップを行います。

npm create plasmo
実行結果
% npm create plasmo

> npx
> create-plasmo

🟣 Plasmo v0.89.3
🔴 The Browser Extension Framework
🟡 Extension name: sample-app
🟡 Extension description: A basic Plasmo extension.
🟡 Author name: Plasmo Corp. <[email protected]>
🔵 INFO   | Creating new project with popup
🔵 INFO   | Installing dependencies...

セットアップ後は以下のような構成となります。

構成
% tree .

.
├── README.md
├── assets
│   └── icon.png
├── node_modules
├── package.json
├── popup.tsx
└── tsconfig.json

popup.tsxでブラウザ拡張をクリックしたときの画面を構成します。

popup.tsx
import { useState } from "react"

function IndexPopup() {
  const [data, setData] = useState("")

  return (
    <div
      style={{
        padding: 16
      }}>
      <h2>
        Welcome to your{" "}
        <a href="https://www.plasmo.com" target="_blank">
          Plasmo
        </a>{" "}
        Extension!
      </h2>
      <input onChange={(e) => setData(e.target.value)} value={data} />
      <a href="https://docs.plasmo.com" target="_blank">
        View Docs
      </a>
    </div>
  )
}

export default IndexPopup

Reactですので、状態管理などもuseStateを使って行うことができます。

一旦、デフォルト状態で開発サーバーを起動してみます。

npm run dev

起動後、buildディレクトリが作成されます。

この中にライブリローディング時の拡張機能ファイル群が格納されます。

拡張機能を有効化するため、以下にアクセスを行います。

chrome://extensions/

アクセス後、デベロッパーモードを有効化して、パッケージ化されていない拡張機能を読み込むをクリックします。

img_48.png

build/chrome-mv3-devを選択して、拡張機能を有効化します。
img.png

有効化後、拡張機能をクリックするとポップアップ画面が確認できます。

img.png

ライブローディングされているかを確認するため、popup.tsxを以下のように変更します。

popup.tsx
import { useState } from "react"

function IndexPopup() {
  const [data, setData] = useState("")

  return (
    <div
      style={{
        padding: 16
      }}>
      <h2>
        Welcome to your{" "}
        <a href="https://www.plasmo.com" target="_blank">
          Plasmo
        </a>{" "}
        Extension!
      </h2>
      <input onChange={(e) => setData(e.target.value)} value={data} />
      <a href="https://docs.plasmo.com" target="_blank">
        View Docs
      </a>
      <h2>
        入力された情報: { data }
      </h2>
    </div>
  )
}

export default IndexPopup

テキストを入力すると、期待通りページ下部にテキストが表示されるようになりました。

img.png

タブページの作成

続いて、タブページを作成してみます。

https://docs.plasmo.com/framework/tab-pages

タブページは、ブラウザ拡張機能内で開くことのできるWeb ページとなっています。

よく説明ページなどで利用されています。

tabsディレクトリ内に配置することでタブページとして機能するようになります。

tabs/description.tsx
function DescriptionPage() {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        padding: 16
      }}>
      <h2>この拡張機能の説明書</h2>
      <p>説明をここにいれます</p>
    </div>
  )
}
 
export default DescriptionPage

popup.tsxから説明書を開けるように変更します。

popup.tsx
import { useState } from "react"

function IndexPopup() {
  const [data, setData] = useState("")

  return (
    <div
      style={{
        padding: 16
      }}>
      <h2>
        <a href="tabs/description.html" target="_blank">
          説明書を見る
        </a>
      </h2>
      <input onChange={(e) => setData(e.target.value)} value={data} />
      <a href="https://docs.plasmo.com" target="_blank">
        View Docs
      </a>
      <h2>
        入力された情報: { data }
      </h2>
    </div>
  )
}

export default IndexPopup

一度開発サーバを再起動すると以下のようにタブページを開くことができます。

img 50.png

ビルドしてみる

では、作ったブラウザ拡張機能をビルドしてみます。

npm run build

ビルド完了後、build/chrome-mv3-prodが作成されているので、初期セットアップで行ったように拡張機能を有効化すると本番用の拡張機能として分けて利用することができます。

img.png

さいごに

今回、Plasmo を初めて使ってみましたが、Reactベースであるため、学習コストもそこまでかからずブラウザ拡張機能を作ることができました。

他にも、Storage機能など必要な機能が一通り揃っているみたいなので、また別の機会に試してみたいと思います。

https://docs.plasmo.com/framework/storage

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.